package com.saianfu.flowable

import com.saianfu.flowable.attendence.ApplyConditionUtil
import com.saianfu.flowable.attendence.ApproveLevel
import com.saianfu.flowable.attendence.EmployeeLevel
import com.saianfu.flowable.attendence.LeaveType
import com.saianfu.flowable.demo.toJsonString
import org.flowable.engine.*
import org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration
import org.flowable.engine.runtime.Execution
import org.flowable.task.api.Task
import org.flowable.task.api.history.HistoricTaskInstance
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

internal class FlowableExTest {
    lateinit var cfg: StandaloneProcessEngineConfiguration
    lateinit var processEngine: ProcessEngine
    lateinit var repositoryService: RepositoryService
    lateinit var runtimeService: RuntimeService
    lateinit var historyService: HistoryService
    lateinit var taskService: TaskService


    @BeforeEach
    fun setUp() {
        cfg = StandaloneProcessEngineConfiguration().also {
            it.jdbcPassword = "123456"
            it.jdbcUsername = "root"
            it.jdbcUrl = "jdbc:mysql://127.0.0.1:3306/flowable?" +
                    "useUnicode=true&characterEncoding=utf-8" +
                    "&useSSL=true" +
                    "&serverTimezone=UTC" +
                    "&nullCatalogMeansCurrent=true" +
                    "&allowMultiQueries=true"
            it.jdbcDriver = "com.mysql.cj.jdbc.Driver"
        }

        processEngine = cfg.buildProcessEngine()
        repositoryService = processEngine.repositoryService
        runtimeService = processEngine.runtimeService
        historyService = processEngine.historyService
        taskService = processEngine.taskService
//        val deployment = repositoryService.createDeployment()
//                .addClasspathResource("processes//Approve003.bpmn20.xml")
//                .deploy()
    }


    @Test
    fun deploy() {
//        FlowableEx.deploy(repositoryService, "processes//Approve003.bpmn20.xml")
    }


    @Test
    fun startProcessInstanceByKey() {
        val employeeLevel = EmployeeLevel.DeputyManager
        val leaveType = LeaveType.AnnualLeave
        val set = ApplyConditionUtil.getApproveLayerList(employeeLevel, leaveType, 0.5f)
        val variables = mutableMapOf<String, Any>()
        variables["_FLOWABLE_SKIP_EXPRESSION_ENABLED"] = true
        if (set.contains(ApproveLevel.HR)) {
            variables["skipHR"] = false
            variables["HRman"] = "hrman"
        } else {
            variables["skipHR"] = true
            variables["HRman"] = ""
        }
        if (set.contains(ApproveLevel.Office)) {
            variables["skipOffice"] = false
            variables["OfficeMan"] = "OfficeMan"
        } else {
            variables["skipOffice"] = true
            variables["OfficeMan"] = ""
        }
        if (set.contains(ApproveLevel.Department)) {
            variables["skipDepartment"] = false
            variables["DepartmentMan"] = "DepartmentMan"
        } else {
            variables["skipDepartment"] = true
            variables["DepartmentMan"] = ""
        }
        if (set.contains(ApproveLevel.BranchLeader)) {
            variables["skipBranchLeader"] = false
            variables["BranchLeaderMan"] = "BranchLeaderMan"
        } else {
            variables["skipBranchLeader"] = true
            variables["BranchLeaderMan"] = ""
        }
        if (set.contains(ApproveLevel.ViceManager)) {
            variables["skipViceManager"] = false
            variables["ViceManagerMan"] = "ViceManagerMan"
        } else {
            variables["skipViceManager"] = true
            variables["ViceManagerMan"] = ""
        }
        if (set.contains(ApproveLevel.GeneralManager)) {
            variables["skipGeneralManager"] = false
            variables["GenernalMangerMan"] = "GenernalMangerMan"
        } else {
            variables["skipGeneralManager"] = true
            variables["GenernalMangerMan"] = ""
        }

        val pi = FlowableEx.startProcessInstanceByKey(runtimeService, "Approve003", variables = variables)
        println(pi.processInstanceId)


    }

    var instanceId = "37501"

    //
    @Test
    fun isProcessRunning() {
        val isRunning = FlowableEx.isProcessRunning(runtimeService, instanceId)
        println(isRunning)
        assert(isRunning)
    }

    //
    @Test
    fun suspendProcessInstance() {
        FlowableEx.suspendProcessInstance(runtimeService, instanceId)


    }

    //
    @Test
    fun activateProcessInstance() {
        FlowableEx.activateProcessInstance(runtimeService, instanceId)

    }

    private fun printHistoricInstance(historicTaskInstance: HistoricTaskInstance) {
        println("historicTaskInstance.assignee:" + historicTaskInstance.assignee)
        println("historicTaskInstance.workTimeInMillis:" + historicTaskInstance.workTimeInMillis)
        println("historicTaskInstance.createTime:" + historicTaskInstance.createTime)
        println("historicTaskInstance.owner:" + historicTaskInstance.owner)
        println("historicTaskInstance.time:" + historicTaskInstance.time)
        println("historicTaskInstance.id:" + historicTaskInstance.id)
        println("historicTaskInstance.processInstanceId:" + historicTaskInstance.processInstanceId)
        println("historicTaskInstance.executionId:" + historicTaskInstance.executionId)
        println("historicTaskInstance.parentTaskId:" + historicTaskInstance.parentTaskId)

        println("-----------historicTaskInstance.processVariables----------")
        historicTaskInstance.processVariables.forEach { t, u ->
            println("$t:$u")
        }
        println("-----------historicTaskInstance.taskLocalVariables----------")
        historicTaskInstance.taskLocalVariables.forEach { t, u ->
            println("$t:$u")
        }
    }

    //
    @Test
    fun deleteProcessInstance() {
        FlowableEx.deleteProcessInstance(runtimeService, instanceId, "搞错了，没用了，删掉")
    }

    //
    @Test
    fun listHistoricTask() {
        val historyInstaceList = FlowableEx.listHistoricTask(historyService, instanceId, 0, 1000)
        println("historyInstaceList:" + historyInstaceList.size)
        historyInstaceList.forEach {
            printHistoricInstance(it)
        }
    }

    //
    @Test
    fun activeTask() {
        val historicTaskInstance = FlowableEx.activeTask(historyService, instanceId)
        printHistoricInstance(historicTaskInstance)

        val list = runtimeService.createExecutionQuery().processInstanceId(instanceId).list()
        list.forEach {
            printExecution(it)
        }
    }

    private fun printExecution(it: Execution) {
        println("--------------printExecution-------------------")
        println("it.id:" + it.id)
        println("it.activityId:" + it.activityId)
        println("it.name:" + it.name)
        println("it.description:" + it.description)
        println("it.isEnded:" + it.isEnded)
        println("it.isSuspended:" + it.isSuspended)
        println("it.superExecutionId:" + it.superExecutionId)
        println("it.processInstanceId:" + it.processInstanceId)
        println("it.parentId:" + it.parentId)
        println("it.rootProcessInstanceId:" + it.rootProcessInstanceId)
    }

    //
//    @Test
//    fun getActivityDiagram() {
//    }
//
    @Test
    fun completeTask() {
//        val taskList = taskService.createTaskQuery().list()
//        taskList.forEach {
//            printTask(it)
//        }
//        val currentTask = FlowableEx.activeTask(historyService, instanceId)
//        val variables = mutableMapOf(
//                Pair("HRResult", 1),
//                Pair("OfficeResult", -1),
//                Pair("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true)
//        )
//
//        FlowableEx.completeTask(taskService, currentTask.id, variables)

        FlowableEx.completeTask(taskService, "37519", mutableMapOf())
    }

    @Test
    fun completeTaskDepartment() {
//        val taskList = taskService.createTaskQuery().list()
//        taskList.forEach {
//            printTask(it)
//        }
        val currentTask = FlowableEx.activeTask(historyService, instanceId)
        val variables = mutableMapOf(
                Pair("DepartmentResult", 1),
                Pair("BranchLeaderResult", -1),
                Pair("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true)
        )

        FlowableEx.completeTask(taskService, currentTask.id, variables)

    }

    @Test
    fun completeTaskBranchLeader() {
//        val taskList = taskService.createTaskQuery().list()
//        taskList.forEach {
//            printTask(it)
//        }
        val currentTask = FlowableEx.activeTask(historyService, instanceId)
        val variables = mutableMapOf(
                Pair("BranchLeaderResult", 0),
                Pair("ViceManagerResult", -1),
                Pair("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true)
        )

        FlowableEx.completeTask(taskService, currentTask.id, variables)

    }

    private fun printTask(task: Task?) {
        task?.let {
            println("------------printTask---------------")
            println("it.id:" + it.id)
            println("it.name:" + it.name)
        }
    }

    //
    @Test
    fun transferTask() {
        val taskId = FlowableEx.activeTask2(taskService, instanceId)?.first()?.id
        println(taskId)
        FlowableEx.transferTask(taskService, taskId!!, "transfer001", "transfer001")
    }

    //
    @Test
    fun delegateTask() {
        val taskId = FlowableEx.activeTask2(taskService, instanceId)?.first()?.id
        println(taskId)
        FlowableEx.delegateTask(taskService, taskId, "transfer001", "pei")
    }


    @Test
    fun resolveTask() {
        val variables = mutableMapOf(
                Pair("HRResult", 1),
                Pair("OfficeResult", -1),
                Pair("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true)
        )
        FlowableEx.resolveTask(taskService, "37519", variables)
    }

    //
//    @Test
//    fun addComment() {
//    }
//
//    @Test
//    fun listComment() {
//    }
//
//    @Test
//    fun claim() {
//    }
//
//    @Test
//    fun unclaim() {
//    }
//
    @Test
    fun taskByCondition() {
        val list = FlowableEx.taskByCondition(taskService, mutableMapOf(), "hrman", 2, 0, 100)
        println("id\tassignee\tprocessInstanceId")
        list.forEach {
            it.id
            println("${it.id}\t${it.assignee}\t${it.processInstanceId}")
        }
    }

    @Test
    fun testTest() {
        val list = historyService.createHistoricTaskInstanceQuery().taskAssignee("hrman").list()
        println("taskCount:" + list.count())

        val processInstance = historyService.createProcessInstanceHistoryLogQuery(instanceId).includeTasks().includeVariables().singleResult()
        println(processInstance.id)
        processInstance.historicData.forEach {
            println("time=${it.time}")
        }
//        list.forEach {
//            printHistoricInstance(it)
//        }

    }

    //
//    @Test
//    fun countTaskByCondition() {
//    }
//
    @Test
    fun listVariableByTaskId() {
        val list = FlowableEx.activeTask2(taskService, instanceId)
        val taskId = list.first().id
        val varargsMap = FlowableEx.listVariableByTaskId(taskService, taskId)

        varargsMap.forEach { t, u ->
            println("$t -- $u")
        }
    }

    @AfterEach
    fun tearDown() {
    }

    @Test
    fun activeTask2() {
        val list = FlowableEx.activeTask2(taskService, instanceId)
        println("activeTask2:" + list.size)
        list.forEach {
            println("${it.id} - ${it.assignee}")
        }
    }

}